package controller;

import entity.FileSystem;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class FileAction {

    //注入Redisson对象用于使用分布式锁
    @Autowired
    private Redisson redisson;

    @RequestMapping("upload")
    public String upload(MultipartHttpServletRequest request, Model model) {

        //定义锁id
        String fileUploadKey = "FileUploadLock";

        //从请求中获取上传的文件对象
        MultipartFile file = request.getFile("fname");

        //有分布式锁
        if(file.getOriginalFilename() != ""){
            //通过Redisson对象获取锁
            RLock lock = redisson.getLock(fileUploadKey);
            //上锁，过期时间30秒
            lock.lock(30, TimeUnit.SECONDS);

            try {
                //调用上传文件方法
                FileSystem fileSystem = uploadFile(file);
                //将文件信息对象返回到前端
                model.addAttribute("fileSystem",fileSystem);
                System.out.println("有锁上传完毕");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //释放锁
                lock.unlock();
            }
        }

        /*//没有分布式锁
        if(file.getOriginalFilename() != ""){
            try {
                //调用上传文件方法
                FileSystem fileSystem = uploadFile(file);
                //将文件信息对象返回到前端
                model.addAttribute("fileSystem",fileSystem);
                System.out.println("无锁上传完毕");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }*/

        //逻辑视图跳转
        return "index";
    }

    /*
        上传文件到FastDFS的方法
     */
    public FileSystem uploadFile(MultipartFile file) throws Exception{

        //声明一个FileSystem对象用于记录文件信息
        FileSystem fileSystem = new FileSystem();

        //把文件保存到web服务器
        //从文件对象中获取文件的原始名称
        String originalFilename = file.getOriginalFilename();
        //截取字符串获取文件的后缀
        String houzhui = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        //生成新文件名
        String newFileName = UUID.randomUUID().toString() +"."+ houzhui;
        //创建web服务器保存文件的目录
        File toSaveFile = new File("G:/upload/" + newFileName);
        //将路径转换成文件
        file.transferTo(toSaveFile);
        //获取服务器的绝对路径
        String newFilePath = toSaveFile.getAbsolutePath();

        //模拟延时2秒
        Thread.sleep(2000);

        //把文件从web服务器上传到FastDFS
        //加载配置文件
        ClientGlobal.initByProperties("config/fastdfs-client.properties");
        //创建tracker客户端
        TrackerClient trackerClient = new TrackerClient();
        //通过客户端获取连接服务并返回
        TrackerServer trackerServer = trackerClient.getConnection();
        //声明storage服务
        StorageServer storageServer = null;
        //定义storage客户端
        StorageClient1 client = new StorageClient1(trackerServer, storageServer);
        //定义文件元信息
        NameValuePair[] list = new NameValuePair[1];
        //将原始文件名赋值到元信息中
        list[0] = new NameValuePair("fileName",originalFilename);
        //上传文件到FastDFS，参数为（文件的绝对路径，文件的后缀名，文件元信息）
        String fileId = client.upload_file1(newFilePath, houzhui, list);
        //关闭tracker客户端
        trackerServer.close();

        //封装fileSystem数据对象
        fileSystem.setFileId(fileId);
        fileSystem.setFileName(originalFilename);
        fileSystem.setFilePath(fileId); //已经上传到FastDFS上，通过ID访问，所以fileId也为文件路径

        //返回文件信息对象
        return fileSystem;


    }

    @Bean
    public Redisson redisson(){
        Config config = new Config();
        //使用单个redis
        config.useSingleServer().setAddress("redis://192.168.80.128:6379").setDatabase(0);
        //返回Redisson对象
        return (Redisson)Redisson.create(config);
    }
}
